﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.ServiceModel.Web;
using System.Text;
using System.Web;
using Wams.Admin.UI.Models;

namespace Wams.Admin.UI
{
    [ServiceContract(Namespace = "")]
    [ServiceBehavior(IncludeExceptionDetailInFaults = true)]
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    public class InstanceControl
    {
        // To use HTTP GET, add [WebGet] attribute. (Default ResponseFormat is WebMessageFormat.Json)
        // To create an operation that returns XML,
        //     add [WebGet(ResponseFormat=WebMessageFormat.Xml)],
        //     and include the following line in the operation body:
        //         WebOperationContext.Current.OutgoingResponse.ContentType = "text/xml";
        [OperationContract]
        public JSDashboard GetDashboardUpdate()
        {
            HttpCookie authCookie = HttpContext.Current.Request.Cookies["wamsUI.auth"];
            if (authCookie == null || string.IsNullOrEmpty(authCookie.Value)) return new JSDashboard() { Error = "Access denied." };
            if (!Auth.CheckToken(authCookie.Value, true)) return new JSDashboard() { Error = "Access denied." };

            JSDashboard result = new JSDashboard();

            // Load site list from settings file.
            WamsSettings settings = WamsSettings.Load(Utils.StorageAccount, Utils.ContainerName);
            result.Sites = new List<JSSite>();
            foreach (var site in settings.Sites)
            {
                result.Sites.Add(new JSSite()
                {
                    Id = site.Id,
                    Name = site.Name,
                    Source = site.Source,
                    Url = site.Url
                });
            }

            // Populate deployments and instance data.
            Dictionary<string, JSDeployment> deployments = new Dictionary<string, JSDeployment>();
            foreach (WamsInstanceState instance in Wams.Admin.WamsInstances.GetAllInstances(Utils.ContainerName, Utils.StorageAccount))
            {
                JSInstance inst = new JSInstance()
                {
                    Id = instance.InstanceId,
                    Status = instance.Status,
                    IsBusy = instance.IsBusy
                };
                JSDeployment deploymentForInstance = null;
                if (deployments.ContainsKey(instance.DeploymentId)) deploymentForInstance = deployments[instance.DeploymentId];
                else 
                {
                    deploymentForInstance = new JSDeployment() { Id = instance.DeploymentId, Instances = new List<JSInstance>() };
                    deployments.Add(instance.DeploymentId, deploymentForInstance);
                }
                deploymentForInstance.Instances.Add(inst);

                // For each instance, get status for each site.
                inst.SiteStatuses = new List<JSInstanceSiteState>();
                foreach (JSSite site in result.Sites)
                {
                    WamsSiteState siteState = WamsInstances.GetSiteState(Utils.StorageAccount, Utils.ContainerName,instance.DeploymentInstanceId,site.Id);
                    if (siteState == null) continue;
                    inst.SiteStatuses.Add(new JSInstanceSiteState()
                     {
                         DeploymentId = deploymentForInstance.Id,
                         InstanceId = inst.Id,
                         SiteId = site.Id,
                         Status = siteState.Status
                     });
                }
            }
            result.Deployments = deployments.Values.ToList();


            return result;
        }
        [OperationContract]
        public JSMessage AddSite(string siteName)
        {
            HttpCookie authCookie = HttpContext.Current.Request.Cookies["wamsUI.auth"];
            if (authCookie == null || string.IsNullOrEmpty(authCookie.Value)) return new JSMessage() { Error = "Access denied." };
            if (!Auth.CheckToken(authCookie.Value, true)) return new JSMessage() { Error = "Access denied." };

            if (string.IsNullOrEmpty(siteName)) return new JSMessage() { Error = "Name cannot be empty" };

            // Load site list from settings file.
            WamsSettings settings = WamsSettings.Load(Utils.StorageAccount, Utils.ContainerName);
            int count =0;
            while (true)
            {
                if (!settings.Sites.Any(x=> x.Id == count)) break;
                count++;
            }
            if (settings.Sites.Any(x => x.Name.ToLower() == siteName.ToLower())) return new JSMessage() { Error = "Site already exists." };
            settings.Sites.Add(new WamsSite() { Name = siteName, Id = count });
            settings.SaveSettingsFile(Utils.StorageAccount, Utils.ContainerName);
            return null;
        }

        [OperationContract]
        public JSSiteBindingList GetSiteBindings(int siteId)
        {
            HttpCookie authCookie = HttpContext.Current.Request.Cookies["wamsUI.auth"];
            if (authCookie == null || string.IsNullOrEmpty(authCookie.Value)) return new JSSiteBindingList() { Error = "Access denied." };
            if (!Auth.CheckToken(authCookie.Value, true)) return new JSSiteBindingList() { Error = "Access denied." };

            WamsSettings settings = WamsSettings.Load(Utils.StorageAccount, Utils.ContainerName);
            var site = settings.Sites.Where(x => x.Id == siteId).FirstOrDefault();
            if (site == null) return new JSSiteBindingList() { Error = "Site not found." };
            else return new JSSiteBindingList()
            {
                Bindings = site.Bindings.Select(x => new JSSiteBinding
                    {
                        Cert = x.CertificateHash,
                        Host = x.BindingInfo.Split(':')[2],
                        Port = int.Parse(x.BindingInfo.Split(':')[1])
                    }).ToArray()
            };
        }

        [OperationContract]
        public JSMessage RequestContentSync(string deploymentId, int instanceId, int siteId)
        {
            HttpCookie authCookie = HttpContext.Current.Request.Cookies["wamsUI.auth"];
            if (authCookie == null || string.IsNullOrEmpty(authCookie.Value)) return new JSMessage() { Error = "Access denied." };
            if (!Auth.CheckToken(authCookie.Value, true)) return new JSMessage() { Error = "Access denied." };

            SyncContentMessage msg = WamsMessage.SyncContent;
            msg.SiteId = siteId;
            msg.Send(Utils.ContainerName, Utils.StorageAccount, deploymentId, instanceId);
            SetSiteStateStatusToWaiting(deploymentId, instanceId, siteId);
            return new JSMessage();
        }

        [OperationContract]
        public JSMessage SaveSiteDetails(int siteId, string siteName, string siteUrl)
        {
            HttpCookie authCookie = HttpContext.Current.Request.Cookies["wamsUI.auth"];
            if (authCookie == null || string.IsNullOrEmpty(authCookie.Value)) return new JSMessage() { Error = "Access denied." };
            if (!Auth.CheckToken(authCookie.Value, true)) return new JSMessage() { Error = "Access denied." };

            WamsSettings settings = WamsSettings.Load(Utils.StorageAccount, Utils.ContainerName);
            var site = settings.Sites.Where(x => x.Id == siteId).FirstOrDefault();
            if (site == null) return new JSMessage() { Error = "Site not found." };
            site.Name = siteName;
            site.Url = siteUrl;
            settings.SaveSettingsFile(Utils.StorageAccount, Utils.ContainerName);
            return new JSMessage();
        }
        [OperationContract]
        public JSMessage SaveInstanceBusyStatus(string deploymentId, int instanceId, bool busyStatus)
        {
            HttpCookie authCookie = HttpContext.Current.Request.Cookies["wamsUI.auth"];
            if (authCookie == null || string.IsNullOrEmpty(authCookie.Value)) return new JSMessage() { Error = "Access denied." };
            if (!Auth.CheckToken(authCookie.Value, true)) return new JSMessage() { Error = "Access denied." };

            SetBusyStateMessage msg = WamsMessage.SetBusyState;
            msg.IsBusy = busyStatus;
            msg.Send(Utils.ContainerName, Utils.StorageAccount, deploymentId, instanceId);
            SetInstanceStateToWaiting(deploymentId, instanceId);
            return new JSMessage();
        }

        public void SetInstanceStateToWaiting(string deploymentId, int instanceId)
        {
            WamsInstances.OverrideInstanceStatus(Utils.ContainerName, Utils.StorageAccount, deploymentId, instanceId, InstanceStatus.Waiting);
        }
        public void SetSiteStateStatusToWaiting(string deploymentId, int instanceId, int siteId)
        {
            WamsInstances.OverrideSiteStateStatus(Utils.ContainerName, Utils.StorageAccount, deploymentId, instanceId, siteId, SiteStatus.Waiting);
        }

        [OperationContract]
        public JSMessage SaveSiteBindings(int siteId, JSSiteBinding[] bindings, bool applyToInstances)
        {
            HttpCookie authCookie = HttpContext.Current.Request.Cookies["wamsUI.auth"];
            if (authCookie == null || string.IsNullOrEmpty(authCookie.Value)) return new JSMessage() { Error = "Access denied." };
            if (!Auth.CheckToken(authCookie.Value, true)) return new JSMessage() { Error = "Access denied." };

            WamsSettings settings = WamsSettings.Load(Utils.StorageAccount, Utils.ContainerName);
            var site = settings.Sites.Where(x => x.Id == siteId).FirstOrDefault();
            if (site == null) return new JSMessage() { Error = "Site not found." };

            site.Bindings.Clear();

            foreach (var binding in bindings)
            {
                site.Bindings.Add(new WamsSiteBinding()
                {
                    BindingType = string.IsNullOrEmpty(binding.Cert) ? WamsBindingType.Http : WamsBindingType.Https,
                    CertificateHash = binding.Cert,
                    BindingInfo = "*:" + binding.Port + ":" + binding.Host
                });
            }
            settings.SaveSettingsFile(Utils.StorageAccount, Utils.ContainerName);

            if (applyToInstances)
            {
                List<WamsInstanceState> instances = WamsInstances.GetAllInstances(Utils.ContainerName, Utils.StorageAccount);
                foreach (WamsInstanceState inst in instances)
                {
                    SyncSettingsMessage syncSettings = WamsMessage.SyncSettings;
                    syncSettings.SiteId = siteId;
                    syncSettings.Send(Utils.ContainerName, Utils.StorageAccount, inst.DeploymentId, inst.InstanceId);
                    SetSiteStateStatusToWaiting(inst.DeploymentId, inst.InstanceId, siteId);
                }
            }

            return new JSMessage();
        }
    }
}